#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2016-04-25 22:27:47
# @Author  : Zhaifg (zhaifengguo@foxmail.com)
# @Link    : http://htop.me
# @Version : $Id$

import os
import xml.etree.ElementTree as ET
import paramiko
import platform
# import Exception


class SshNoPasswdException(Exception):
    def __init__(self, username):
        self.username = username

    def __str__(self):
        return repr(self.username)


class CannotFindKeyException(Exception):
    def __str__(self):
        return repr("There was not exist the key")


class SSHClientErr(ValueError):
    pass


class UploadFileOver(ValueError):
    pass


def calls(a=10, b=10):
    if a == b:
        raise UploadFileOver()


class SSHClient(object):
    def __init__(self, hostname, username, isKey=None, password=None, port=22):
        self.hostname = hostname
        self.username = username
        self.port = port
        self._sftp = None
        self._client = None
        self._transport = None
        self.isKey = isKey

        if isKey is not None and isKey.upper() == 'R':
            default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
            try:
                if os.path.isfile(default_path):
                    #self.key = paramiko.RSAKey.from_private_key_file(default_path)
                    self.key = default_path
                else:
                    raise CannotFindKeyException()
            except CannotFindKeyException, e:
                print e
        elif isKey is not None and isKey.upper() == 'd':
            default_path = os.path.join(os.environ['HOME'], '.ssh', 'id_dsa')
            try:
                if os.path.isfile(default_path):
                    #self.key = paramiko.DSAKey.from_private_key_file(default_path)
                    self.key = default_path
                else:
                    raise CannotFindKeyExcepotion()
            except CannotFindKeyException, e:
                print e
        else:
            try:
                if password is None:
                    raise SshNoPasswdException(self.username)
                else:
                    self.password = password
            except SshNoPasswdException, e:
                print e

    def _setSftp(self):
        if self._client is None:
            self._setClient()
        # else:
        #     self._transport = self._client.get_transport()
        # self._sftp = paramiko.SFTPClient.from_transport(self._transport)
        self._sftp = self._client.open_sftp()

    def getSftp(self):
        if self._sftp is None:
            self._setSftp()
        return self._sftp

    def _setClient(self):
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            if self.isKey is None:
                client.connect(self.hostname, username=self.username,
                               password=self.password, port=self.port)
            else:
                client.connect(self.hostname, username=self.username,
                               key_filename=self.key)
        except paramiko.AuthenticationException, e:
            print "Login Error"
            print e
            return False
        self._client = client

    def put(self, local, remote, callback=None, confirm=True):
        return self._put(local, remote, callback=callback, confirm=True)

    def get(self, remote, local):
        return self._get(remote, local)

    def exec_command(self, command):
        return self._exec_command(command)

    def _exec_command(self, command):
        if self._client is None:
            self._setClient()

        return self._client.exec_command(command)

    def isAbspath(self, path):
        if path.startswith('/'):
            return True
        return False
        # os_version = platform.system()
        # if os_version == 'Linux':
        #     if path.startswith('/'):
        #         return True
        #     return False
        # elif os_version == 'Windows':

    def _put(self, local, remote, callback=None, confirm=True):
        try:
            if self._sftp is None:
                self._setSftp()
            if callback is None:
                callback = calls
            self._sftp.put(local, remote, callback=callback, confirm=confirm)
        except UploadFileOver:
            return True
        except Exception, e:
            return False

    def _get(self, remote, local):
        try:
            if self._sftp is None:
                self._setSftp()
            self._sftp.get(remote, local)
            return True
        except Exception, e:
            print 'get error', e
            return False

    def close(self):
        self.__del__()

    def __del__(self):
        if self._transport is not None:
            self._transport.close()
        if self._sftp is not None:
            self._sftp.close()
        if self._client is not None:
            self._client.close()

    def move(self, src, dst):
        if self.isAbspath(src) and self.isAbspath(dst):
            if self.isExist(dst):
                raise SSHClientErr('%s is already exist')
            cmd = 'mv %s %s' % (src, dst)
            stdin, stdout, stderr = self._exec_command(cmd)
            if stderr.read():
                return False
            return True
        else:
            raise SSHClientErr('%s or %s is not abspath' % (src, dst))

    def isExist(self, fname):
        cmd = 'ls %s' % fname
        stdin, stdout, stderr = self._exec_command(cmd)
        if stderr.read():
            return False
        return True
        # try:
        #     if self._sftp is None:
        #         self.getSftp()
        #     if fname in self._sftp(path):
        #         return True
        #     return False
        # except IOError, e:
        #     print 'fname:%s, path:%s' % (fname, path)
        #     return False

    def verifyLogin(self):
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            if self.isKey is None:
                client.connect(self.hostname, username=self.username,
                               password=self.password, port=self.port)
                print "OK"
                return True
            else:
                client.connect(self.hostname, username=self.username,
                               key_filename=self.key)
                return True
        except paramiko.AuthenticationException, e:
            return False
        except:
            return False


def indent(elem, level=0):
    i = "\n" + level * "  "
    j = "\n" + (level - 1) * "  "
    if len(elem):
        if not elem.text or not elem.text.strip():
            elem.text = i + "  "
        if not elem.tail or not elem.tail.strip():
            elem.tail = i
        for subelem in elem:
            indent(subelem, level + 1)
        if not elem.tail or not elem.tail.strip():
            elem.tail = j
    else:
        if level and (not elem.tail or not elem.tail.strip()):
            elem.tail = j
    return elem

# 修改tomcat 所有的端口


def setTomcatPort(filename, shutdownPort, httpPort, ajpPort, sslPort):
    tree = ET.parse(filename)
    root = tree.getroot()

    root.set('port', str(shutdownPort))
    for conn in root.iter("Connector"):
        # print conn.attrib['protocol']
        if conn.attrib['protocol'] == 'HTTP/1.1':
            conn.set('port', str(httpPort))
        else:
            conn.set('port', str(ajpPort))

        conn.set('redirectPort', str(sslPort))
    tree.write(filename)


def setContext(docBase, path="", **kwargs):
    context = ET.Element('Context')
    context.set('path', path)
    context.set('docBase', docBase)
    for k, v in kwargs.items():
        context.set(k, v)
    return context


def createElem(elem, **kwargs):
    elem = ET.Element(elem)
    for k, v in kwargs.items():
        elem.set(k, v)
    return elem


def addAlias(filename, hostname, alias):
    pass


def setLog(filename, hostname, dirlog):
    pass


def getCmdClient(host, user, password, port=22):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        client.connect(host, username=user, password=password, port=port)
    except paramiko.AuthenticationException, e:
        return None
    return client


# def calls(a=10, b=10):
#     if a == b:
#         print b
#     # print 'Data Transmission %10f M [%3.2f%%]\r'%
#     # (a/1024./1024,a*100./int(b))

if __name__ == '__main__':
    sshclient = SSHClient('192.168.8.212', 'root', password='yimiwork321')

    # print sshclient
    # stdin, stdout, stderr = sshclient.exec_command('ls /etc/passwds')
    # print stdout.read()
    # print stderr.read()
    # sftp = sshclient.getSftp()
    # print sftp
    # path = "/tmp"
    # fname = 'tomcat7.tar.gz'
    # print sshclient.isExist('/etc/')
    # print sshclient.isAbspath('/sfdd/dd/')
    # print sshclient.move('/root/sssdf', '/root/sssdf')
    # print sftp.listdir('/etc/passwd')
    # if fname in sftp.listdir(path):
    #     print 'OK'gcc-4.8.5.tar.bz2
    # # sshclient.get('/usr/local/tomcat_app005/conf/server.xml', 'D:/xxx--xxss')
    # # sshclient.get('/usr/local/tomcat_app00ll5/conf/server.xml','D:/pacdddd.txt')
    a = "D:\\TDDownload\\gcc-4.8.5.tar.bz2"
    print sshclient.put(a, '/root/server1', callback=calls)
    print 'sssss'

    # sftp.rename('/usr/local/tomcat_app005', '/usr/local/tomcat_appsss')
    # # sshclient.put("D:/Development/EasyOPS/packages/tomcat7.tar.gz", '/root/tomcat7.tar.gz')
    sshclient.close()
    # filename = 'server.xml'
    # tree = ET.parse(filename)
    # root = tree.getroot()

    # engine = root.findall('Service/Engine')[0]
    # # for k, v in service[0].items():
    # #     print k, v
    # host = createElem(
    #     'Host', name='mail.1mi.com', appBase="", unpackWARs='true', autoDeploy='true')
    # context1 = createElem("Context", docBase="/home/webapp/mail", path="")
    # context2 = createElem(
    #     "Context", docBase="/home/webapp/download", path="/download")
    # valve = createElem("Valve", className="org.apache.catalina.valves.AccessLogValve",
    #                    directory="logs",
    #                    prefix="mail_access_log.",
    #                    suffix=".log",
    #                    pattern="""%h %l %u %t "%r" %s %b""")
    # host.append(context1)
    # host.append(context2)
    # host.append(valve)
    # ET.dump(host)
    # engine.append(host)
    # indent(root)
    # tree.write('output.xml')
